-
-
Notifications
You must be signed in to change notification settings - Fork 386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add named capturing groups to regexpToRegexp method #225
Conversation
This looks really great to me, thanks! From my understanding this will work in all current projects because the named group doesn't remove it from the array of RegExp results (e.g. this code depends on the position of keys in the result: Line 405 in 98ab888
For getting this feature into the current version of Express, you'll probably need to make this PR against an older branch here: https://github.com/pillarjs/path-to-regexp/blob/0.1.x/index.js However, I believe this it can land in the next Express.js release with the current implementation. |
src/index.ts
Outdated
@@ -453,13 +453,17 @@ export type Token = string | Key; | |||
function regexpToRegexp(path: RegExp, keys?: Key[]): RegExp { | |||
if (!keys) return path; | |||
|
|||
// Use a negative lookahead to match only capturing groups. | |||
const groups = path.source.match(/\((?!\?)/g); | |||
const groups = path.source.match(/\((\?<.*?>)?(?!\?)/g); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const groups = path.source.match(/\((\?<.*?>)?(?!\?)/g); | |
const groups = path.source.match(/\((?:\?<(.*?)>)?(?!\?)/g); |
Something like this will resolve the comment you have below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, non-capturing groups, I tried that. Had no luck so I'm guessing, I made some mistake :)
Will try this :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something like this will resolve the comment you have below.
That didn't work
$ curl http://localhost:1337/testRegex/testData/extraStuff -w "\n"
{"0":"testRegex","2":"extraStuff","(?<groupname>":"testData"}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah, that makes sense. It's happening with .match
which is only getting the matches and not the groups. We probably need to use regexp.exec
in a loop instead.
There's also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll but it's not supported on earlier node.js versions or browsers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using exec
worked :)
Looping through exec
results doesn't look nice tho.
Any idea how to make it nicer?
@DamianKu You'll probably need to put the tests behind a version flag by checking the node.js version in the test suite. |
Use exec instead of match.
@blakeembrey |
You can read the node.js version here: https://nodejs.org/api/process.html#process_process_version. And use something like https://www.npmjs.com/package/semver to compare whether you want to run it. Put it within an Here's an example (albeit using TypeScript): https://github.com/TypeStrong/ts-node/blob/866bce6a175ec124fe62f269b22e91c92b40f875/src/index.spec.ts#L137 |
Hah OK 😁 I'm aware of that. I don't know why I was thinking that you meant
something more elaborate
…On Tue, 14 Jul 2020, 02:16 Blake Embrey, ***@***.***> wrote:
How I would go about doing that?
You can read the node.js version here:
https://nodejs.org/api/process.html#process_process_version. And use
something like https://www.npmjs.com/package/semver to compare whether
you want to run it. Put it within an if condition to define the test.
Here's an example (albeit using TypeScript):
https://github.com/TypeStrong/ts-node/blob/866bce6a175ec124fe62f269b22e91c92b40f875/src/index.spec.ts#L137
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#225 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AEE7BAKDB6CZDWQ7RT4OIT3R3OWW5ANCNFSM4OKTOBNA>
.
|
I added the If you prefer I can do ternary in const TESTS: Test[] = [
...,
...(gte(process.version, "10.0.0")
? [
[...test...],
[...test...]
]
: ([] as any)),
...,
];
|
src/index.ts
Outdated
modifier: "", | ||
pattern: "" | ||
}); | ||
index++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would probably be good to stay consistent with the behavior in string tokens. In that method, we're only incrementing the counter each non-named group:
Line 189 in 8b0ae94
name: name || key++, |
That would mean you probably want execResult[1] || index++
. We should add a mixed test of named and unnamed groups to make sure it doesn't break.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK will do that.
Does it mean that this /\/(.+)\/(?<groupname>.+)\/(.+)/
called with /testRegex/testData/extraStuff
should result in {"0":"testRegex","1":"extraStuff","groupname":"testData"}
?
…ith non named regexp matching
Thanks @DamianKu! This looks great. |
I was looking into fixing issues raised on express repository #4277.
I modified regular expression in
regexpToRegexp
to match not only(
but also(?<*>
probably regexp could be better :).No change with normal regexp matching,
router.get(/\/regex\/(.+)/)
->localhost/regex/testData
will result in{"0":"testData"}
.With named capturing groups,
router.get(/\/regex2\/(?<groupname>.+)/)
->localhost/regex2/testData
will result in{"groupname":"testData"}
.Mixed matched with named capturing groups,
router.get(/\/(.+)\/(?<groupname>.+)\/(.+)/)
->localhost/testRegex/testData/extraStuff"
will result in{"0":"testRegex","2":"extraStuff","groupname":"testData"}
.All tests are passing but I didn't add new tests to cover this functionality yet.
Would be great to get some feedback from you guys if I'm even looking in good place or is it worth working on it.